package com.moxiao.yfjh.module.blind.service.brokerageUser;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.BooleanUtil;
import com.moxiao.yfjh.framework.common.pojo.PageResult;
import com.moxiao.yfjh.module.blind.common.ErrorCodeConstants;
import com.moxiao.yfjh.module.blind.controller.admin.user.BlindBrokerageUserPageReqVO;
import com.moxiao.yfjh.module.blind.dal.dataobject.brokerageUser.BlindBrokerageUserDO;
import com.moxiao.yfjh.module.blind.dal.mysql.brokerageUser.BlindBrokerageUserMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

import static com.moxiao.yfjh.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 分销用户 Service 实现类
 *
 * @author owen
 */
@Service
@Validated
public class BlindBrokerageUserServiceImpl implements BlindBrokerageUserService {

    @Resource
    private BlindBrokerageUserMapper blindBrokerageUserMapper;


    @Override
    public BlindBrokerageUserDO getBrokerageUser(Long id) {
        return blindBrokerageUserMapper.selectById(id);
    }

    @Override
    public List<BlindBrokerageUserDO> getBrokerageUserList(Collection<Long> ids) {
        return blindBrokerageUserMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<BlindBrokerageUserDO> getBrokerageUserPage(BlindBrokerageUserPageReqVO pageReqVO) {
        List<Long> childIds = getChildUserIdsByLevel(pageReqVO.getBindUserId(), pageReqVO.getLevel());
        // 有”绑定用户编号“查询条件时，没有查到下级会员，直接返回空
        if (pageReqVO.getBindUserId() != null && CollUtil.isEmpty(childIds)) {
            return PageResult.empty();
        }
        return blindBrokerageUserMapper.selectPage(pageReqVO, childIds);
    }

    @Override
    public void updateBrokerageUserId(Long id, Long bindUserId) {
        // 校验存在
        BlindBrokerageUserDO brokerageUser = validateBrokerageUserExists(id);
        // 绑定关系未发生变化
        if (Objects.equals(brokerageUser.getBindUserId(), bindUserId)) {
            return;
        }

        // 情况一：清除推广员
        if (bindUserId == null) {
            // 清除推广员
            blindBrokerageUserMapper.updateBindUserIdAndBindUserTimeToNull(id);
            return;
        }

        // 情况二：修改推广员
        validateCanBindUser(brokerageUser, bindUserId);
        blindBrokerageUserMapper.updateById(fillBindUserData(bindUserId, new BlindBrokerageUserDO().setId(id)));
    }

    @Override
    public void updateBrokerageUserEnabled(Long id, Boolean enabled) {
        // 校验存在
        validateBrokerageUserExists(id);
        if (BooleanUtil.isTrue(enabled)) {
            // 开通推广资格
            blindBrokerageUserMapper.updateById(new BlindBrokerageUserDO().setId(id)
                    .setBrokerageEnabled(true).setBrokerageTime(LocalDateTime.now()));
        } else {
            // 取消推广资格
            blindBrokerageUserMapper.updateEnabledFalseAndBrokerageTimeToNull(id);
        }
    }

    private BlindBrokerageUserDO validateBrokerageUserExists(Long id) {
        BlindBrokerageUserDO brokerageUserDO = blindBrokerageUserMapper.selectById(id);
        if (brokerageUserDO == null) {
            throw com.moxiao.yfjh.framework.common.exception.util.ServiceExceptionUtil.exception(ErrorCodeConstants.BROKERAGE_USER_NOT_EXISTS);
        }

        return brokerageUserDO;
    }

    @Override
    public BlindBrokerageUserDO getBindBrokerageUser(Long id) {
        return Optional.ofNullable(id)
                .map(this::getBrokerageUser)
                .map(BlindBrokerageUserDO::getBindUserId)
                .map(this::getBrokerageUser)
                .orElse(null);
    }

    @Override
    public boolean updateUserPrice(Long id, Integer price) {
        if (price > 0) {
            blindBrokerageUserMapper.updatePriceIncr(id, price);
        } else if (price < 0) {
            return blindBrokerageUserMapper.updatePriceDecr(id, price) > 0;
        }
        return true;
    }

    @Override
    public void updateUserFrozenPrice(Long id, Integer frozenPrice) {
        if (frozenPrice > 0) {
            blindBrokerageUserMapper.updateFrozenPriceIncr(id, frozenPrice);
        } else if (frozenPrice < 0) {
            blindBrokerageUserMapper.updateFrozenPriceDecr(id, frozenPrice);
        }
    }

    @Override
    public void updateFrozenPriceDecrAndPriceIncr(Long id, Integer frozenPrice) {
        Assert.isTrue(frozenPrice < 0);
        int updateRows = blindBrokerageUserMapper.updateFrozenPriceDecrAndPriceIncr(id, frozenPrice);
        if (updateRows == 0) {
            throw exception(ErrorCodeConstants.BROKERAGE_USER_FROZEN_PRICE_NOT_ENOUGH);
        }
    }

    @Override
    public Long getBrokerageUserCountByBindUserId(Long bindUserId, Integer level) {
        List<Long> childIds = getChildUserIdsByLevel(bindUserId, level);
        return (long) CollUtil.size(childIds);
    }

    @Override
    public boolean bindBrokerageUser(Long userId, Long bindUserId) {
        // 1. 获得分销用户
        boolean isNewBrokerageUser = false;
        BlindBrokerageUserDO brokerageUser = blindBrokerageUserMapper.selectById(userId);
        if (brokerageUser == null) { // 分销用户不存在的情况：1. 新注册；2. 旧数据；3. 分销功能关闭后又打开
            isNewBrokerageUser = true;
            brokerageUser = new BlindBrokerageUserDO().setId(userId).setBrokerageEnabled(false).setBrokeragePrice(0).setFrozenPrice(0);
        }

        // 2.1 校验是否能绑定用户
        boolean validated = isUserCanBind(brokerageUser);
        if (!validated) {
            return false;
        }
        // 2.3 校验能否绑定
        validateCanBindUser(brokerageUser, bindUserId);
        // 2.3 绑定用户
        if (isNewBrokerageUser) {
//            Integer enabledCondition = tradeConfigService.getTradeConfig().getBrokerageEnabledCondition();
//            if (BlindBrokerageEnabledConditionEnum.ALL.getCondition().equals(enabledCondition)) { // 人人分销：用户默认就有分销资格
//                brokerageUser.setBrokerageEnabled(true).setBrokerageTime(LocalDateTime.now());
//            }
            brokerageUser.setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now());
            blindBrokerageUserMapper.insert(fillBindUserData(bindUserId, brokerageUser));
        } else {
            blindBrokerageUserMapper.updateById(fillBindUserData(bindUserId, new BlindBrokerageUserDO().setId(userId)));
        }
        return true;
    }

    /**
     * 补全绑定用户的字段
     *
     * @param bindUserId    绑定的用户编号
     * @param brokerageUser update 对象
     * @return 补全后的 update 对象
     */
    private BlindBrokerageUserDO fillBindUserData(Long bindUserId, BlindBrokerageUserDO brokerageUser) {
        return brokerageUser.setBindUserId(bindUserId).setBindUserTime(LocalDateTime.now());
    }


    private boolean isUserCanBind(BlindBrokerageUserDO user) {

        return true;
    }


    private void validateCanBindUser(BlindBrokerageUserDO user, Long bindUserId) {
        // 校验要绑定的用户有无推广资格
        BlindBrokerageUserDO bindUser = blindBrokerageUserMapper.selectById(bindUserId);
        if (bindUser == null || BooleanUtil.isFalse(bindUser.getBrokerageEnabled())) {
            throw exception(ErrorCodeConstants.BROKERAGE_BIND_USER_NOT_ENABLED);
        }

        // 校验绑定自己
        if (Objects.equals(user.getId(), bindUserId)) {
            throw exception(ErrorCodeConstants.BROKERAGE_BIND_SELF);
        }

    }

    /**
     * 根据绑定用户编号，获得下级用户编号列表
     *
     * @param bindUserId 绑定用户编号
     * @param level      下级用户的层级。
     *                   如果 level 为空，则查询 1+2 两个层级
     * @return 下级用户编号列表
     */
    private List<Long> getChildUserIdsByLevel(Long bindUserId, Integer level) {
        if (bindUserId == null) {
            return Collections.emptyList();
        }
        throw exception(ErrorCodeConstants.BROKERAGE_USER_LEVEL_NOT_SUPPORT);
    }

}
